package com.struts.invocation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.struts.config.ActionConfig;
import com.struts.context.ActionContext;
import com.struts.interceptor.Interceptor;

public class InvocationWrap {

	private Iterator<Interceptor> interceptors;
	private Object action;
	private ActionConfig config;
	private ActionContext invocationContext;

	public InvocationWrap(List<String> interceptorClassNames, ActionConfig config, HttpServletRequest request,
			HttpServletResponse response) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {

		// 拦截器
		if (interceptorClassNames != null && interceptorClassNames.size() > 0) {
			List<Interceptor> list = new ArrayList<Interceptor>();
			for (String className : interceptorClassNames) {
				Interceptor interceptor = (Interceptor) Class.forName(className).getDeclaredConstructor().newInstance();
				interceptor.init();
				list.add(interceptor);
			}
			interceptors = list.iterator();
		}
		this.config = config;
		action = Class.forName(config.getClassName()).getDeclaredConstructor().newInstance();
		invocationContext = new ActionContext(request, response, action);
	}

	public String invoke(InvocationWrap invocation) throws IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, NoSuchMethodException, SecurityException {
		String result = null;
		if (interceptors != null && interceptors.hasNext() && result == null) {
			Interceptor interceptor = interceptors.next();
			result = interceptor.intercept(invocation);
		} else {
			String methodName = config.getMethod();
			Method method = action.getClass().getMethod(methodName);
			result = (String) method.invoke(action);
		}
		return result;
	}

	public ActionContext getInvocationContext() {
		return invocationContext;
	}

	public void setInvocationContext(ActionContext invocationContext) {
		this.invocationContext = invocationContext;
	}
}
